package com.spring.common.exception;


import com.google.common.collect.ImmutableMap;
import com.spring.common.dtos.ResponseResult;
import groovy.util.logging.Log4j2;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;


@ControllerAdvice
@Log4j2
public class ExceptionCatch {
    private static final Logger log = LoggerFactory.getLogger(ExceptionCatch.class);
    // 使用 ImmutableMap 缓存异常类型与响应结果的映射关系 ，ImmutableMap 是一个不可变的 Map ，线程安全
    private static ImmutableMap<Class<? extends Throwable>,ResponseResult> EXCEPTIONS;
    //使用 builder 构建 ImmutableMap 异常类型和错误代码的异常映射关系
    private static ImmutableMap.Builder<Class<? extends Throwable>, ResponseResult> builder = ImmutableMap.builder();

    //捕获Exception异常，并返回响应结果
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResponseResult exception(Exception exception){
        //记录异常日志
        log.error("catch Exception:{}",exception.getMessage());
        if (EXCEPTIONS == null){
            EXCEPTIONS = builder.build();
        }
            final ResponseResult result = EXCEPTIONS.get(exception.getClass());
            if(result!=null){
                //如果匹配了异常类型，则返回对应的响应结果
                return result;
            }else{
                //如果没有匹配异常类型，则返回默认的响应结果
                return ResponseResult.errorResult(999,"出现未知异常，请联系管理员");
            }
        }
    static {
        //初始化常见异常类型和响应结果的映射关系
        builder.put(HttpMessageNotReadableException.class,ResponseResult.errorResult(400,"请求参数解析失败"));
        builder.put(NullPointerException.class,ResponseResult.errorResult(500,"空指针异常"));
        builder.put(IndexOutOfBoundsException.class,ResponseResult.errorResult(1,"数组越界异常"));
        //该项目中其他异常类型，如自定义异常等，在这里添加即可
        builder.put(ArithmeticException.class,ResponseResult.errorResult(2,"除数不能为0"));
    }

}
